package com.youfang.sixthmedia.net;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.Map;

import android.os.AsyncTask;

import com.gzit.common.async.LoadingCallback;

public class Chain {

	public class Task {

		Request req;
		Response resp;
		Task next;

		public Task(Request req, Response resp) {
			this.req = req;
			this.resp = resp;
		}

		public void execute() {

			new AsyncTask<Request, Integer, Response>() {
				protected void onPostExecute(Response result) {

					try {
						if (!callback.process(result, Chain.this)) {
							loading.hideLoading();
							return;
						}
					} catch (Exception e) {
						loading.hideLoading();
						callback.onException(e);
						destroy();
						return;
					}

					// 如果处理成功，则取下一个任务
					if (next != null) {
						next.execute();
						return;
					}

					// 在最后一环销毁掉任务链
					destroy();

				};

				@Override
				protected Response doInBackground(Request... params) {
					curTask = Task.this;
					HttpRemoter.doRemote(req, resp);
					return resp;
				}

			}.execute(req);

		}

	}

	private LinkedList<Task> chianedTasks = new LinkedList<Task>();
	private ChainAsynCallbak<Response> callback;
	private LoadingCallback loading;
	private Task curTask;
	private Map<String, Object> context = new HashMap<String, Object>();

	public Map<String, Object> getContext() {
		return context;
	}

	public void destroy() {
		this.chianedTasks.clear();
		this.context.clear();
		this.callback = null;
		this.loading = null;

	}

	public Task getCurTask() {
		return curTask;
	}

	public void setCurTask(Task curTask) {
		this.curTask = curTask;
	}

	public Chain prepare(ChainAsynCallbak<Response> callback,
			LoadingCallback loading) {
		this.callback = callback;
		this.loading = loading;
		return this;
	}

	public Chain join(Request req, Response resp) {

		Task task = new Task(req, resp);
		Task prev = this.chianedTasks.isEmpty() ? null : this.chianedTasks
				.getLast();
		if (prev != null) {
			prev.next = task;

		}
		this.chianedTasks.add(task);
		return this;
	}

	public Chain execute() {
		if (this.chianedTasks.isEmpty()) {
			return this;
		}

		this.loading.showLoading();
		this.chianedTasks.getFirst().execute();
		return this;

	}

}